import React, { useRef, useEffect, useState } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import './ModelViewer.css';

interface ModelViewerProps {
  modelName?: string;
}

export const ModelViewer: React.FC<ModelViewerProps> = ({ modelName }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const [autoRotate, setAutoRotate] = useState(true);
  const canvasRef = useRef<HTMLDivElement>(null);
  
  // Three.js 相关对象的引用
  const mountedRef = useRef(false);
  const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
  const sceneRef = useRef<THREE.Scene | null>(null);
  const cameraRef = useRef<THREE.PerspectiveCamera | null>(null);
  const controlsRef = useRef<OrbitControls | null>(null);
  const animationIdRef = useRef<number | null>(null);
  const modelRef = useRef<THREE.Group | null>(null);
  
  // 创建默认几何体
  const createDefaultModel = (scene: THREE.Scene) => {
    // 移除当前模型
    if (modelRef.current) {
      scene.remove(modelRef.current);
      modelRef.current = null;
    }
    
    // 创建药材胶囊形状组合
    const group = new THREE.Group();
    
    // 主体
    const geometry = new THREE.CapsuleGeometry(1, 1.5, 8, 16);
    const material = new THREE.MeshStandardMaterial({ 
      color: 0x8F5733,
      roughness: 0.7,
      metalness: 0.1
    });
    const capsule = new THREE.Mesh(geometry, material);
    group.add(capsule);
    
    // 添加纹理特征
    const detailGeometry = new THREE.TorusGeometry(0.3, 0.1, 8, 12);
    const detailMaterial = new THREE.MeshStandardMaterial({ 
      color: 0x654321,
      roughness: 0.9
    });
    
    const detail1 = new THREE.Mesh(detailGeometry, detailMaterial);
    detail1.position.set(0, 0, 1.1);
    detail1.rotation.set(Math.PI/2, 0, 0);
    detail1.scale.set(1, 1, 0.3);
    group.add(detail1);
    
    // 添加点特征
    const smallSphereGeom = new THREE.SphereGeometry(0.1, 8, 8);
    const smallSphereMat = new THREE.MeshStandardMaterial({ color: 0x5D4037 });
    
    for (let i = 0; i < 10; i++) {
      const sphere = new THREE.Mesh(smallSphereGeom, smallSphereMat);
      // 随机位置
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.random() * Math.PI - Math.PI/2;
      const r = 1.1;
      sphere.position.set(
        r * Math.cos(theta) * Math.cos(phi),
        r * Math.sin(phi),
        r * Math.sin(theta) * Math.cos(phi)
      );
      sphere.scale.set(0.8 + Math.random() * 0.4, 0.8 + Math.random() * 0.4, 0.8 + Math.random() * 0.4);
      group.add(sphere);
    }
    
    modelRef.current = group;
    scene.add(group);
  };
  
  // 初始化三维场景
  const initThreeJS = () => {
    if (!containerRef.current) return;
    
    // 确保没有重复初始化
    if (mountedRef.current) return;
    mountedRef.current = true;
    
    // 容器尺寸
    const container = containerRef.current;
    const width = container.clientWidth;
    const height = container.clientHeight;
    
    // 初始化场景
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0xf8f8f8);
    sceneRef.current = scene;
    
    // 添加环境光和方向光
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
    scene.add(ambientLight);
    
    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
    directionalLight.position.set(1, 1, 1);
    scene.add(directionalLight);

    const backLight = new THREE.DirectionalLight(0xffffff, 0.5);
    backLight.position.set(-1, 0.5, -1);
    scene.add(backLight);
    
    // 设置相机
    const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);
    camera.position.set(0, 0, 5);
    cameraRef.current = camera;
    
    // 设置渲染器
    const renderer = new THREE.WebGLRenderer({ 
      antialias: true,
      alpha: true
    });
    renderer.setSize(width, height);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.shadowMap.enabled = true;
    rendererRef.current = renderer;
    
    // 创建canvas容器
    const canvasContainer = document.createElement('div');
    canvasContainer.className = 'canvas-container';
    canvasContainer.appendChild(renderer.domElement);
    canvasRef.current = canvasContainer;
    
    // 添加到DOM
    container.appendChild(canvasContainer);
    
    // 添加控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    controls.minDistance = 2.5;
    controls.maxDistance = 10;
    controls.autoRotate = autoRotate;
    controls.autoRotateSpeed = 3.0;
    controlsRef.current = controls;
    
    // 创建默认模型
    createDefaultModel(scene);
    
    // 启动动画循环
    const animate = () => {
      if (!mountedRef.current) return;
      
      animationIdRef.current = requestAnimationFrame(animate);
      
      if (controlsRef.current) {
        controlsRef.current.update();
      }
      
      if (rendererRef.current && sceneRef.current && cameraRef.current) {
        rendererRef.current.render(sceneRef.current, cameraRef.current);
      }
    };
    
    animate();
    
    // 处理窗口大小变化
    const handleResize = () => {
      if (!containerRef.current || !cameraRef.current || !rendererRef.current) return;
      
      const width = containerRef.current.clientWidth;
      const height = containerRef.current.clientHeight;
      
      cameraRef.current.aspect = width / height;
      cameraRef.current.updateProjectionMatrix();
      
      rendererRef.current.setSize(width, height);
    };
    
    window.addEventListener('resize', handleResize);
    
    // 在effect cleanup函数中保存删除事件监听器的引用
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  };
  
  // 清理三维场景资源
  const cleanupThreeJS = () => {
    if (!mountedRef.current) return;
    mountedRef.current = false;
    
    // 取消动画帧
    if (animationIdRef.current !== null) {
      cancelAnimationFrame(animationIdRef.current);
      animationIdRef.current = null;
    }
    
    // 释放控制器
    if (controlsRef.current) {
      controlsRef.current.dispose();
      controlsRef.current = null;
    }
    
    // 释放渲染器
    if (rendererRef.current) {
      rendererRef.current.dispose();
      rendererRef.current = null;
    }
    
    // 从DOM中移除canvas容器
    if (canvasRef.current && containerRef.current && containerRef.current.contains(canvasRef.current)) {
      try {
        containerRef.current.removeChild(canvasRef.current);
      } catch (err) {
        console.log('清理canvas容器时出错:', err);
      }
    }
    
    // 清空场景和模型引用
    if (sceneRef.current && modelRef.current) {
      sceneRef.current.remove(modelRef.current);
      modelRef.current = null;
    }
    
    sceneRef.current = null;
    cameraRef.current = null;
  };
  
  // 加载3D模型
  const loadModel = () => {
    if (!modelName || !sceneRef.current) return;
    
    setLoading(true);
    setError(false);
    
    const loader = new GLTFLoader();
    const modelUrl = `/models/${modelName}.glb`;
    
    console.log(`尝试加载模型: ${modelUrl}`);
    
    loader.load(
      modelUrl,
      (gltf) => {
        if (!mountedRef.current || !sceneRef.current) {
          return; // 组件已卸载，不进行后续操作
        }
        
        console.log(`模型加载成功: ${modelUrl}`);
        
        try {
          const model = gltf.scene;
          
          // 移除当前模型
          if (modelRef.current) {
            sceneRef.current.remove(modelRef.current);
            modelRef.current = null;
          }
          
          // 计算包围盒以适配视图
          const box = new THREE.Box3().setFromObject(model);
          const size = box.getSize(new THREE.Vector3());
          const center = box.getCenter(new THREE.Vector3());
          
          // 调整模型位置和缩放
          model.position.x = -center.x;
          model.position.y = -center.y;
          model.position.z = -center.z;
          
          const maxDim = Math.max(size.x, size.y, size.z);
          if (maxDim > 0) {
            const scale = 2 / maxDim;
            model.scale.set(scale, scale, scale);
          }
          
          modelRef.current = model;
          sceneRef.current.add(model);
        } catch (err) {
          console.error(`处理模型时出错:`, err);
          // 保持默认模型
        }
        
        setLoading(false);
      },
      (xhr) => {
        const progress = (xhr.loaded / xhr.total) * 100;
        console.log(`模型加载进度: ${Math.round(progress)}%`);
      },
      (error) => {
        if (!mountedRef.current) return; // 组件已卸载，不进行后续操作
        
        console.error(`加载3D模型出错 ${modelUrl}:`, error);
        setError(true);
        setLoading(false);
      }
    );
  };
  
  // 控制自动旋转
  const toggleAutoRotate = () => {
    setAutoRotate(prev => !prev);
    if (controlsRef.current) {
      controlsRef.current.autoRotate = !autoRotate;
    }
  };
  
  // 组件挂载时初始化场景
  useEffect(() => {
    const cleanup = initThreeJS();
    
    // 组件卸载时清理资源
    return () => {
      if (cleanup) cleanup();
      cleanupThreeJS();
    };
  }, []);
  
  // 当modelName或autoRotate变化时更新
  useEffect(() => {
    // 更新控制器的自动旋转设置
    if (controlsRef.current) {
      controlsRef.current.autoRotate = autoRotate;
    }
    
    // 如果初始化完成且场景存在，尝试加载模型
    if (mountedRef.current && sceneRef.current) {
      if (!modelName) {
        // 如果没有模型名称，确保使用默认模型并停止加载
        createDefaultModel(sceneRef.current);
        setLoading(false);
      } else {
        // 加载指定模型
        loadModel();
      }
    }
  }, [modelName, autoRotate]);
  
  return (
    <div className="model-viewer" ref={containerRef}>
      {loading && (
        <div className="model-loading">
          <div className="model-spinner"></div>
          <div style={{ marginTop: '10px' }}>加载中...</div>
        </div>
      )}
      {error && !loading && (
        <div className="model-error">
          <div>模型加载失败，显示默认模型</div>
        </div>
      )}
      <div className="model-controls">
        <button className="model-control-btn" onClick={toggleAutoRotate} title={autoRotate ? "停止旋转" : "开始旋转"}>
          {autoRotate ? "⏹" : "⟳"}
        </button>
      </div>
    </div>
  );
}; 